#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/wait.h>  
#include <unistd.h>  
#include <signal.h>  

#define MAXARGS  20    // 最大参数数量  
#define ARGLEN   100   // 每个参数的最大长度  

/**  
 * 从输入缓冲区创建一个新的字符串，移除末尾的换行符并分配内存  
 * @param buf 输入缓冲区  
 * @return 新分配的字符串  
 */  
char *makestring(char *buf) {  
    char *cp;  

    buf[strlen(buf) - 1] = '\0';        // 移除换行符  
    cp = malloc(strlen(buf) + 1);       // 分配内存  
    if (cp == NULL) {                    // 检查内存分配是否成功  
        fprintf(stderr, "no memory\n");  
        exit(1);  
    }  
    strcpy(cp, buf);                     // 拷贝字符串  
    return cp;                           // 返回新字符串  
}  

/**  
 * 执行命令  
 * @param arglist 参数列表  
 */  
void execute(char *arglist[]) {  
    int pid, exitstatus;  

    pid = fork();                        // 创建子进程  
    switch (pid) {  
        case -1:  
            // fork调用失败，输出错误信息并退出  
            perror("fork failed");  
            exit(1);  
        case 0:  
            // 子进程：执行命令  
            execvp(arglist[0], arglist);  
            // execvp失败，输出错误信息并退出  
            perror("execvp failed");  
            exit(1);  
        default:  
            // 父进程：等待特定子进程结束  
            while (wait(&exitstatus) != pid)  
                ; // 空循环，直到等待的子进程结束  
            // 打印子进程的退出状态  
            printf("child exited with status %d, %d\n",  
                   exitstatus >> 8, exitstatus & 0377);  
    }  
}  

int main() {  
    char *arglist[MAXARGS + 1];  // 参数列表，最后一个元素为NULL  
    int numargs;                  // 当前参数数量  
    char argbuf[ARGLEN];          // 输入缓冲区  

    numargs = 0;  
    while (numargs < MAXARGS) {   // 允许最多MAXARGS个参数  
        printf("Arg[%d]? ", numargs);  
        // 读取输入，并检查是否为空行  
        if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n') {  
            arglist[numargs++] = makestring(argbuf);  // 添加参数到列表  
        } else {  
            if (numargs > 0) {             // 如果有参数，执行命令  
                arglist[numargs] = NULL;   // 参数列表末尾设置为NULL  
                execute(arglist);          // 执行命令  
                numargs = 0;               // 重置参数计数  
            }  
        }  
    }  
    return 0;  
}